
<script setup>
import {onMounted, ref} from 'vue';

const props = defineProps({
  data: {
    type: String,
    default: '{}',
  },
})

const jsonInput = ref(props.data);
const formattedJson = ref('');
const error = ref('');

const formatJson = () => {
  try {
    const parsedJson = JSON.parse(jsonInput.value);
    formattedJson.value = JSON.stringify(parsedJson, null, 2);
    error.value = '';
  } catch (e) {
    error.value = '无效的 JSON 格式';
    formattedJson.value = '{}';
  }
};

const highlightJson = (json) => {
  const lines = json.split('\n');
  const highlightedLines = lines.map(line => {
    let highlightedLine = line;
    // 替换字符串
    highlightedLine = highlightedLine.replace(/("[^"]*")/g, (match) => {
      return `<span class="json-string">${match}</span>`;
    });
    // 替换键
    highlightedLine = highlightedLine.replace(/("[^"]*"):/g, (match) => {
      return `<span class="json-key">${match}</span>`;
    });
    // 替换布尔值和 null
    highlightedLine = highlightedLine.replace(/\b(true|false|null)\b/g, (match) => {
      return `<span class="json-boolean">${match}</span>`;
    });
    // 替换数字
    highlightedLine = highlightedLine.replace(/\b\d+\b/g, (match) => {
      return `<span class="json-number">${match}</span>`;
    });
    return highlightedLine;
  });
  return highlightedLines.join('\n');
};

onMounted(()=>{
  // 格式化JSON数据
  formatJson()
})
</script>

<template>
  <div class="json-editor">
    <div class="editor-container">
      <div class="editor-section">
        <div v-if="error" class="error-message">{{ error }}</div>
        <div v-else class="output-container">
          <pre v-html="highlightJson(formattedJson)" class="json-output"></pre>
        </div>
      </div>
    </div>
  </div>
</template>

<style>
.json-editor {
  width: 100%; /* 宽度占满父容器 */
  min-height: 60%; /* 高度占满父容器 */
  display: flex;
  flex-direction: column;
  padding: 20px;
  box-sizing: border-box; /* 确保 padding 不会影响宽度和高度 */
}

.editor-container {
  display: flex;
  flex-direction: column;
  gap: 10px;
  flex: 1; /* 占满剩余空间 */
}

.editor-section {
  background-color: #2d2d44;
  border: 1px solid #444;
  border-radius: 8px;
  padding: 10px;
  flex: 1; /* 占满剩余空间 */
  display: flex;
  flex-direction: column;
}

.output-container {
  flex: 1; /* 占满剩余空间 */
  overflow: hidden;
}

.output-container:hover {
  overflow-y: auto;
}

/* 美化滚动条 */
.output-container::-webkit-scrollbar {
  width: 8px;
}

.output-container::-webkit-scrollbar-track {
  background: #2d2d44;
  border-radius: 4px;
}

.output-container::-webkit-scrollbar-thumb {
  background: #42b983;
  border-radius: 4px;
}

.output-container::-webkit-scrollbar-thumb:hover {
  background: #3aa876;
}

.json-output {
  margin: 0;
  font-family: monospace;
  font-size: 14px;
  white-space: pre-wrap;
  word-wrap: break-word;
  color: #ffffff;
  box-sizing: border-box; /* 确保 padding 不会影响宽度和高度 */
}

.error-message {
  margin-top: 10px;
  color: #ff4d4f;
  font-size: 14px;
}

/* JSON 高亮样式 */
.json-key {
  color: #42b983;
}

.json-string {
  color: #ff79c6;
}

.json-boolean {
  color: #bd93f9;
}

.json-number {
  color: #f1fa8c;
}
</style>